/**
 * @file    Containers.h
 * @brief   Includes generic container-classes: List, Map.
 ****************************************************************************
 * @version $Id: Containers.h 2868 2010-08-07 21:13:01Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_Containers_H__
 #define __WOSH_Core_Containers_H__

 #include <woshDefs.h>
 #include <core/Reflection.h>
 #include <core/Mutex.h>

 #include <map>
 #include <vector>

 
namespace wosh {


/**
 * @class   wosh::ListT
 * @brief   
 ****************************************************************************
 *
 * @ingroup DataModels
 ****************************************************************************
 * @version 0.8.384 $Id $
 * @author  Alessandro Polo
 ****************************************************************************/
template <typename T>
class ListT
 {
	WOSH_CLASSNAME(wosh::ListT)
	WOSH_CLASS_ABSTRACT(false)

	public:
		typedef typename std::vector<T>::iterator Iterator;
		typedef typename std::vector<T>::const_iterator ConstIterator;
		typedef typename std::vector<T>::reverse_iterator IteratorReverse;
		typedef typename std::vector<T>::const_reverse_iterator ConstIteratorReverse;

	public:
		/**
		 * @brief  Default constructor.
		 */
		ListT() { }

		ListT( const ListT<T>& m ) {
		 }

		virtual ~ListT() {
		 }


/** @name reentrant methods
 * @{
 ******************************************************************************/
	public:
		inline int count() const {
			MutexLockerRead mL(&this->mux);
			return this->list.size();
		 }

		inline bool isEmpty() const {
			MutexLockerRead mL(&this->mux);
			return this->list.empty();
		 }

		virtual inline void clear() {
			MutexLockerWrite mL(&this->mux);
			free();
		 }

		inline void append( const T& item ) {
			MutexLockerRead mL(&this->mux);
			this->list.push_back(item);
		 }

//@}
/** @name non-reentrant (proxy for STL methods)
 * @{
 ******************************************************************************/
	public:
		inline bool exists( const T& item ) const {
			return ( indexOf(item) != -1 );
		 }

		inline int indexOf( const T& item ) const {
			int index = 0;
			ConstIterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++index ) {
				if ( *it == item ) return index;
			 }
			return -1;
		 }

		inline const T& itemAt( int index ) const {
			int iLoc = 0;
			ConstIterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++iLoc ) {
				if ( index == iLoc ) return *it;
			 }
			return NULL;
		 }
		inline T& itemAt( int index ) {
			int iLoc = 0;
			Iterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++iLoc ) {
				if ( index == iLoc ) return *it;
			 }
			return NULL;
		 }
		inline Iterator find( int index ) {
			int iLoc = 0;
			Iterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++iLoc ) {
				if ( iLoc != index ) continue;
				return it;
			 }
			return this->list.end();
		 }

		virtual void free() {
			this->list.clear();
		 }

		inline void push_back( const T& item, bool check_existence = false ) {
			if ( check_existence && exists(item) )
				return;
			this->list.push_back(item);
		 }

		 // BUGGY
		inline void set( int index, const T& item ) {
			if ( index < 0 ) return;
			this->list[index] = item;
		 }


//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline ConstIterator begin() const					{ return this->list.begin(); }
		inline Iterator begin()								{ return this->list.begin(); }
		inline ConstIteratorReverse rbegin() const			{ return this->list.rbegin(); }
		inline IteratorReverse rbegin()						{ return this->list.rbegin(); }

		inline ConstIterator back() const					{ return this->list.back(); }
		inline Iterator back()								{ return this->list.back(); }
		inline ConstIteratorReverse rback() const			{ return this->list.rback(); }
		inline IteratorReverse rback()						{ return this->list.rback(); }

		inline ConstIterator end() const					{ return this->list.end(); }
		inline Iterator end()								{ return this->list.end(); }
		inline ConstIteratorReverse rend() const			{ return this->list.rend(); }
		inline IteratorReverse rend()						{ return this->list.rend(); }

		inline const T& frontItem() const					{ return this->list.front(); }
		inline T& frontItem()								{ return this->list.front(); }

		inline const T& backItem() const					{ return this->list.back(); }
		inline T& backItem()								{ return this->list.back(); }

		inline int size() const								{ return this->list.size(); }

		inline const std::vector<T*>& getVector() const		{ return this->list; }
		inline std::vector<T*>& getVector()					{ return this->list; }

		inline void transactionBeginRead() const			{ this->mux.lockForRead(); }
		inline void transactionBeginWrite() const			{ this->mux.lockForWrite(); }
		inline void transactionEnd() const					{ this->mux.unLock(); }

		inline MutexRW* getMutex() const					{ return &this->mux; }

//@}
/** @name Operators Overloading
 * @{
 ******************************************************************************/
	public:



//@}
	protected:
		mutable std::vector<T> list;
		mutable MutexRW mux;


}; // class def



template <class T>  
class ListT<T*>
 {
	WOSH_CLASSNAME(wosh::ListT)
	WOSH_CLASS_ABSTRACT(false)

	public:
		typedef typename std::vector<T*>::iterator Iterator;
		typedef typename std::vector<T*>::const_iterator ConstIterator;
		typedef typename std::vector<T*>::reverse_iterator IteratorReverse;
		typedef typename std::vector<T*>::const_reverse_iterator ConstIteratorReverse;

	public:
		/**
		 * @brief  Default constructor.
		 */
		ListT() { }

		ListT( const ListT<T*>& m ) {
			*this = m;
		 }

		virtual ~ListT() { }// do not free elements!


/** @name reentrant methods
 * @{
 ******************************************************************************/
	public:
		inline int count() const {
			MutexLockerRead mL(&this->mux);
			return this->list.size();
		 }

		inline bool isEmpty() const {
			MutexLockerRead mL(&this->mux);
			return this->list.empty();
		 }

		virtual inline void clear() {
			MutexLockerWrite mL(&this->mux);
			free();
		 }

		inline void append( T* item ) {
			MutexLockerRead mL(&this->mux);
			this->list.push_back(item);
		 }

//@}
/** @name non-reentrant (proxy for STL methods)
 * @{
 ******************************************************************************/
	public:
		inline bool exists( const T* item ) const {
			return ( indexOf(item) != -1 );
		 }

		inline int indexOf( const T* item ) const {
			int index = 0;
			ConstIterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++index ) {
				if ( *it == item ) return index;
			 }
			return -1;
		 }
		inline Iterator find( int index ) {
			int iLoc = 0;
			Iterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++iLoc ) {
				if ( iLoc != index ) continue;
				return it;
			 }
			return this->list.end();
		 }

		inline const T* itemAt( int index ) const {
			int iLoc = 0;
			ConstIterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++iLoc ) {
				if ( index == iLoc ) return *it;
			 }
			return NULL;
		 }
		inline T* itemAt( int index ) {
			int iLoc = 0;
			Iterator it;
			const ConstIterator it_end = this->list.end();
			for ( it=this->list.begin(); it!=it_end; ++it, ++iLoc ) {
				if ( index == iLoc ) return *it;
			 }
			return NULL;
		 }

		inline bool pop( T* obj ) {
			typename std::vector<T*>::iterator it;
			for ( it=this->list.begin(); it!=this->list.end(); ++it ) {
				if ( *it != obj ) continue;
				this->list.erase(it);
				return true;
			 }
			return false;
		 }

		inline T* pop( int index ) {
			if ( index < 0 || index >= (int)this->list.size() ) return NULL;
			int i=0;
			typename std::vector<T*>::iterator it;
			for ( it=this->list.begin(); it!=this->list.end(); ++it, ++i ) {
				if ( i != index ) continue;
				T* obj = *it;
				this->list.erase(it);
				return obj;
			 }
			return NULL;
		 }

		int clearNullItems() {
			int count = 0;
			Iterator it;
			for( it=this->list.begin(); it!=this->list.end(); ) {
				if ( *it != NULL ) { ++it; continue; }
				it = this->list.erase(it);
				++count;
			 }
			return count;
		 }

		virtual void free() {
			Iterator it;
			const ConstIterator it_end = this->list.end();
			for( it=this->list.begin(); it!=it_end; ++it ) {
				if ( *it == NULL ) continue;
				delete *it;
			 }
			this->list.clear();
		 }

		inline void push_back( T* item, bool check_existence = false ) {
			if ( check_existence && exists(item) )
				return;
			this->list.push_back(item);
		 }

		 // BUGGY
		inline void set( int index, T* item ) {
			if ( index < 0 ) return;
			this->list[index] = item;
		 }

		inline void reserve( int n ) {
			this->list.reserve(n);
			//this->list.assign( n, (T*)NULL );
		 }

		WRESULT erase( Iterator it, bool deleteContent = true ) {
			if ( it == this->list.end() ) return WRET_ERR_PARAM;
			if ( deleteContent && *it != NULL )
				delete *it;
			this->list.erase(it);
			return WRET_OK;
		 }

//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline ConstIterator begin() const					{ return this->list.begin(); }
		inline Iterator begin()								{ return this->list.begin(); }
		inline ConstIteratorReverse rbegin() const			{ return this->list.rbegin(); }
		inline IteratorReverse rbegin()						{ return this->list.rbegin(); }

		inline ConstIterator back() const					{ return this->list.back(); }
		inline Iterator back()								{ return this->list.back(); }
		inline ConstIteratorReverse rback() const			{ return this->list.rback(); }
		inline IteratorReverse rback()						{ return this->list.rback(); }

		inline ConstIterator end() const					{ return this->list.end(); }
		inline Iterator end()								{ return this->list.end(); }
		inline ConstIteratorReverse rend() const			{ return this->list.rend(); }
		inline IteratorReverse rend()						{ return this->list.rend(); }

		inline const T* frontItem() const {
			if ( this->list.empty() ) return NULL;
			return this->list.front();
		 }
		inline T* frontItem() {
			if ( this->list.empty() ) return NULL;
			return this->list.front();
		 }

		inline const T* backItem() const {
			if ( this->list.empty() ) return NULL;
			return this->list.back();
		 }
		inline T* backItem() {
			if ( this->list.empty() ) return NULL;
			return this->list.back();
		 }

		inline int size() const								{ return this->list.size(); }

		inline const std::vector<T*>& getVector() const		{ return this->list; }
		inline std::vector<T*>& getVector()					{ return this->list; }

		inline void transactionBeginRead() const			{ this->mux.lockForRead(); }
		inline void transactionBeginWrite() const			{ this->mux.lockForWrite(); }
		inline void transactionEnd() const					{ this->mux.unLock(); }

		inline MutexRW* getMutex() const					{ return &this->mux; }

//@}
/** @name Operators Overloading
 * @{
 ******************************************************************************/
	public:

		virtual ListT<T*>& operator=( const ListT<T*>& m ) {
			if (this == &m) return *this; // same object?
			m.transactionBeginRead();
			this->transactionBeginWrite();
			free();
			this->list.reserve( m.size() );
			ConstIterator it;
			for ( it=m.list.begin(); it!=m.list.end(); ++it ) {
				if ( *it == NULL ) continue;
				this->list.push_back( *it );
			 }
			transactionEnd();
			m.transactionEnd();
			return *this;
		 }

		virtual bool operator==( const ListT<T*>& other ) const {
			this->transactionBeginRead();
			other.transactionBeginRead();
			if ( this->list.size() != other.list.size() ) {
				other.transactionEnd();
				this->transactionEnd();
				return false;
			 }
			bool result = std::equal( this->list.begin(), this->list.end(), other.list.begin() );
			other.transactionEnd();
			this->transactionEnd();
			return result;
		 }

		virtual bool operator!=( const ListT<T*>& other ) const	{ return !(*this == other);  }

//@}
	protected:
		mutable std::vector<T*> list;
		mutable MutexRW mux;


}; // class def


////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * @class   wosh::MapT
 * @brief   
 ****************************************************************************
 *
 * @ingroup DataModels
 ****************************************************************************
 * @version 0.8.384 $Id $
 * @author  Alessandro Polo
 ****************************************************************************/
template <typename Key, typename Value>  
class MapT
 {
	WOSH_CLASSNAME(wosh::MapT)
	WOSH_CLASS_ABSTRACT(false)

	public:
		typedef typename std::map<Key,Value>::iterator Iterator;
		typedef typename std::map<Key,Value>::const_iterator ConstIterator;
		typedef typename std::map<Key,Value>::reverse_iterator IteratorReverse;
		typedef typename std::map<Key,Value>::const_reverse_iterator ConstIteratorReverse;

	public:
		/**
		 * @brief  Default constructor.
		 */
		MapT() { }

		MapT( const MapT<Key,Value>& m ) {
		//	*this = m;
		 }

		virtual ~MapT() {
		 }


/** @name reentrant methods
 * @{
 ******************************************************************************/
	public:

		inline int count() const {
			MutexLockerRead mL(&this->mux);
			return this->map.size();
		 }

		inline bool isEmpty() const {
			MutexLockerRead mL(&this->mux);
			return this->map.empty();
		 }

		inline void clear() {
			MutexLockerWrite mL(&this->mux);
			this->map.clear();
		 }

		WRESULT remove( const Key& key ) {
			MutexLockerWrite mL(&this->mux);
			Iterator it = this->map.find(key);
			if ( it == this->map.end() )
				return WRET_ERR_PARAM;
			this->map.erase(it);
			return WRET_OK;
		 }


		void set( const Key& key, const Value& value ) {
			this->map[key] = value;
		 }

		//BUGGY
		Value& find( const Key& key ) {
			return this->map[key];
		 }
		ConstIterator itemAt( int index ) const {
			ConstIterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it;
			 }
			return this->map.end();
		 }
		Iterator itemAt( int index ) {
			Iterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it;
			 }
			return this->map.end();
		 }

		WRESULT erase( const Key& key ) {
			Iterator it = this->map.find(key);
			if ( it == this->map.end() )
				return WRET_ERR_PARAM;
			this->map.erase(it);
			return WRET_OK;
		 }
		WRESULT erase( Iterator it ) {
			if ( it == this->map.end() ) return WRET_ERR_PARAM;
			this->map.erase(it);
			return WRET_OK;
		 }

		inline bool exists( const Key& key ) const {
			ConstIterator it = this->map.find(key);
			return ( it != this->map.end() );
		 }

//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline ConstIterator begin() const					{ return this->map.begin(); }
		inline Iterator begin()								{ return this->map.begin(); }
		inline ConstIteratorReverse rbegin() const			{ return this->map.rbegin(); }
		inline IteratorReverse rbegin()						{ return this->map.rbegin(); }

		inline ConstIterator back() const					{ return this->map.back(); }
		inline Iterator back()								{ return this->map.back(); }
		inline ConstIteratorReverse rback() const			{ return this->map.rback(); }
		inline IteratorReverse rback()						{ return this->map.rback(); }

		inline ConstIterator end() const					{ return this->map.end(); }
		inline Iterator end()								{ return this->map.end(); }
		inline ConstIteratorReverse rend() const			{ return this->map.rend(); }
		inline IteratorReverse rend()						{ return this->map.rend(); }

		inline int size() const								{ return this->map.size(); }

		inline const std::map<Key,Value>& getMap() const	{ return this->map; }
		inline std::map<Key,Value>& getMap()				{ return this->map; }

		inline void transactionBeginRead() const			{ this->mux.lockForRead(); }
		inline void transactionBeginWrite() const			{ this->mux.lockForWrite(); }
		inline void transactionEnd() const					{ this->mux.unLock(); }

		inline MutexRW* getMutex() const					{ return &this->mux; }

//@}

	protected:
		mutable std::map<Key,Value> map;
		mutable MutexRW mux;

};

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

template <typename Key, class Value>  
class MapT<Key, Value*>
 {
	WOSH_CLASSNAME(wosh::MapT)
	WOSH_CLASS_ABSTRACT(false)

	public:
		typedef typename std::map<Key,Value*>::iterator Iterator;
		typedef typename std::map<Key,Value*>::const_iterator ConstIterator;
		typedef typename std::map<Key,Value*>::reverse_iterator IteratorReverse;
		typedef typename std::map<Key,Value*>::const_reverse_iterator ConstIteratorReverse;

	public:
		/**
		 * @brief  Default constructor.
		 */
		MapT() { }

		MapT( const MapT<Key,Value*>& ) { }

		virtual ~MapT() { }// do not free elements!

/** @name reentrant methods
 * @{
 ******************************************************************************/
	public:

		inline int count() const {
			MutexLockerRead mL(&this->mux);
			return this->map.size();
		 }

		inline bool isEmpty() const {
			MutexLockerRead mL(&this->mux);
			return this->map.empty();
		 }

		inline void clear() {
			MutexLockerWrite mL(&this->mux);
			free();
		 }

		inline WRESULT remove( const Key& key, bool delete_content = true ) {
			MutexLockerWrite mL(&this->mux);
			return erase(key, delete_content);
		 }

		inline void copyTo( MapT<Key,Value*>& targetMap, bool deletePrevious = true ) const {
			if (this == &targetMap) return; // same object?
			this->transactionBeginRead();
			targetMap.transactionBeginWrite();
			ConstIterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				if ( deletePrevious && targetMap.find(it->first) != NULL )
					delete targetMap.find(it->first);
				if ( it->second == NULL )
					targetMap.map[it->first] = NULL;
				else
					targetMap.map[it->first] = new Value(*it->second);
			 }
			targetMap.transactionEnd();
			this->transactionEnd();
		 }

/** @name try
 * @{
 ******************************************************************************/
	public:
		void set( const Key& key, Value* value ) {
			this->map[key] = value;
		 }

		WRESULT erase( const Key& key, bool delete_content = true ) {
			Iterator it = this->map.find(key);
			if ( it == this->map.end() ) return WRET_ERR_PARAM;
			if ( it->second == NULL ) {
				this->map.erase(it);
				return WRET_ERR_PARAM;
			 }
			if ( delete_content ) delete it->second;
			this->map.erase(it);
			return WRET_OK;
		 }
		WRESULT erase( Iterator it, bool delete_content = true ) {
			if ( it == this->map.end() ) return WRET_ERR_PARAM;
			if ( delete_content && it->second != NULL )
				delete it->second;
			this->map.erase(it);
			return WRET_OK;
		 }

		WRESULT eraseByValue( Value* item, bool delete_content = true ) {
			Iterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				if ( it->second != item ) continue;
				if ( delete_content )
					delete it->second;
				this->map.erase(it);
				return WRET_OK;
			 }
			return WRET_ERR_PARAM;
		 }

		inline bool exists( const Key& key ) const {
			ConstIterator it = this->map.find(key);
			return ( it != this->map.end() );
		 }

		inline bool existsValue( const Value* item ) const {
			ConstIterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				if ( it->second == item ) return true;
			 }
			return false;
		 }

		const Value* find( const Key& key ) const {
			const ConstIterator it = this->map.find(key);
			if ( it == this->map.end() ) return NULL;
			if ( it->second == NULL ) return NULL;
			return it->second;
		 }

		Value* find( const Key& key ) {
			Iterator it = this->map.find(key);
			if ( it == this->map.end() ) return NULL;
			if ( it->second == NULL ) return NULL;
			return it->second;
		 }

		const Value* valueAt( int index ) const {
			ConstIterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it->second;
			 }
			return NULL;
		 }
		Value* valueAt( int index ) {
			Iterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it->second;
			 }
			return NULL;
		 }

		Key keyAt( int index ) const { // it's a copy
			ConstIterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it->first;
			 }
			return Key();
		 }

		int clearNullValues() {
			int count = 0; bool editing = true; Iterator it;
			while(editing) {
				editing = false;
				for( it=this->map.begin(); it!=this->map.end(); ++it ) {
					if ( it->second != NULL ) continue;
					this->map.erase(it);
					++count;
					editing = true;
					break;
				 }
			 }
			return count;
		 }

		void free() {
			Iterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				if ( it->second == NULL ) continue;
				delete it->second;
			 }
			this->map.clear();
		 }

		int getKeys( std::vector<Key>& keys ) const {
			ConstIterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				keys.push_back(it->first);
			 }
			return keys.size();
		 }

		int getValues( std::vector<Value*>& values ) const {
			ConstIterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				values.push_back(it->second);
			 }
			return values.size();
		 }

//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline ConstIterator begin() const					{ return this->map.begin(); }
		inline Iterator begin()								{ return this->map.begin(); }
		inline ConstIteratorReverse rbegin() const			{ return this->map.rbegin(); }
		inline IteratorReverse rbegin()						{ return this->map.rbegin(); }

		inline ConstIterator back() const					{ return this->map.back(); }
		inline Iterator back()								{ return this->map.back(); }
		inline ConstIteratorReverse rback() const			{ return this->map.rback(); }
		inline IteratorReverse rback()						{ return this->map.rback(); }

		inline ConstIterator end() const					{ return this->map.end(); }
		inline Iterator end()								{ return this->map.end(); }
		inline ConstIteratorReverse rend() const			{ return this->map.rend(); }
		inline IteratorReverse rend()						{ return this->map.rend(); }

		inline int size() const								{ return this->map.size(); }

		inline const std::map<Key,Value*>& getMap() const	{ return this->map; }
		inline std::map<Key,Value*>& getMap()				{ return this->map; }

		inline void transactionBeginRead() const			{ this->mux.lockForRead(); }
		inline void transactionBeginWrite() const			{ this->mux.lockForWrite(); }
		inline void transactionEnd() const					{ this->mux.unLock(); }

		inline MutexRW* getMutex() const					{ return &this->mux; }

//@}
		virtual MapT<Key,Value*>& operator=(const MapT<Key,Value*>& ) {
			return *this;
		 }

		virtual bool operator==( const MapT<Key,Value*>& other ) const {
			this->transactionBeginRead();
			other.transactionBeginRead();
			if ( this->map.size() != other.map.size() ) {
				other.transactionEnd();
				this->transactionEnd();
				return false;
			 }
			bool result = std::equal( this->map.begin(), this->map.end(), other.map.begin() );
			other.transactionEnd();
			this->transactionEnd();
			return result;
		 }

		virtual bool operator!=( const MapT<Key,Value*> &other ) const	{ return !(*this == other);  }


	protected:
		mutable std::map<Key,Value*> map;
		mutable MutexRW mux;

}; // class def

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

template <class Key, typename Value>  
class MapT<Key*, Value>
 {
	WOSH_CLASSNAME(wosh::MapT)
	WOSH_CLASS_ABSTRACT(false)

	public:
		typedef typename std::map<Key*,Value>::iterator Iterator;
		typedef typename std::map<Key*,Value>::const_iterator ConstIterator;
		typedef typename std::map<Key*,Value>::reverse_iterator IteratorReverse;
		typedef typename std::map<Key*,Value>::const_reverse_iterator ConstIteratorReverse;

	public:
		/**
		 * @brief  Default constructor.
		 */
		MapT() { }

		MapT( const MapT<Key*,Value>& ) { }

		virtual ~MapT() { }// do not free elements!

/** @name reentrant methods
 * @{
 ******************************************************************************/
	public:

		inline int count() const {
			MutexLockerRead mL(&this->mux);
			return this->map.size();
		 }

		inline bool isEmpty() const {
			MutexLockerRead mL(&this->mux);
			return this->map.empty();
		 }

		inline void clear() {
			MutexLockerWrite mL(&this->mux);
			free();
		 }

		inline WRESULT remove( const Key* key, bool delete_content = true ) {
			MutexLockerWrite mL(&this->mux);
			return erase(key, delete_content);
		 }


/** @name try
 * @{
 ******************************************************************************/
	public:
		void set( Key* key, const Value& value ) {
			this->map[key] = value;
		 }

		WRESULT erase( const Key* key, bool delete_content = true ) {
			Iterator it = this->map.find(key);
			if ( it == this->map.end() ) return WRET_ERR_PARAM;
			if ( it->first == NULL ) {
				this->map.erase(it);
				return WRET_ERR_PARAM;
			 }
			if ( delete_content ) delete it->first;
			this->map.erase(it);
			return WRET_OK;
		 }
		WRESULT erase( Iterator it, bool delete_content = true ) {
			if ( it == this->map.end() ) return WRET_ERR_PARAM;
			if ( delete_content && it->first != NULL )
				delete it->first;
			this->map.erase(it);
			return WRET_OK;
		 }

		WRESULT eraseByValue( const Value& item, bool delete_content = true ) {
			Iterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				if ( it->second != item ) continue;
				if ( delete_content )
					delete it->first;
				this->map.erase(it);
				return WRET_OK;
			 }
			return WRET_ERR_PARAM;
		 }

		inline bool exists( const Key* key ) const {
			ConstIterator it = this->map.find(key);
			return ( it != this->map.end() );
		 }

		inline bool existsValue( const Value& item ) const {
			ConstIterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				if ( it->second == item ) return true;
			 }
			return false;
		 }

		const Value& find( const Key* key ) const {
			const ConstIterator it = this->map.find(key);
			return it->second;
		 }

		Value& find( const Key* key ) {
			Iterator it = this->map.find(key);
			return it->second;
		 }

		const Value& valueAt( int index ) const {
			ConstIterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it->second;
			 }
			return Value();
		 }
		Value& valueAt( int index ) {
			Iterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it->second;
			 }
			return Value();
		 }

		Key* keyAt( int index ) const { // it's a copy
			ConstIterator it; int ci = 0;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it, ++ci ) {
				if ( index == ci ) return it->first;
			 }
			return NULL;
		 }

		int clearNullValues() {
			int count = 0; bool editing = true; Iterator it;
			while(editing) {
				editing = false;
				for( it=this->map.begin(); it!=this->map.end(); ++it ) {
					if ( it->first != NULL ) continue;
					this->map.erase(it);
					++count;
					editing = true;
					break;
				 }
			 }
			return count;
		 }

		void free() {
			Iterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				if ( it->first == NULL ) continue;
				delete it->first;
			 }
			this->map.clear();
		 }

		int getKeys( std::vector<Key*>& keys ) const {
			ConstIterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				keys.push_back(it->first);
			 }
			return keys.size();
		 }

		int getValues( std::vector<Value>& values ) const {
			ConstIterator it;
			const ConstIterator it_end = this->map.end();
			for( it=this->map.begin(); it!=it_end; ++it ) {
				values.push_back(it->second);
			 }
			return values.size();
		 }

//@}
/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline ConstIterator begin() const					{ return this->map.begin(); }
		inline Iterator begin()								{ return this->map.begin(); }
		inline ConstIteratorReverse rbegin() const			{ return this->map.rbegin(); }
		inline IteratorReverse rbegin()						{ return this->map.rbegin(); }

		inline ConstIterator back() const					{ return this->list.back(); }
		inline Iterator back()								{ return this->list.back(); }
		inline ConstIteratorReverse rback() const			{ return this->list.rback(); }
		inline IteratorReverse rback()						{ return this->list.rback(); }

		inline ConstIterator end() const					{ return this->map.end(); }
		inline Iterator end()								{ return this->map.end(); }
		inline ConstIteratorReverse rend() const			{ return this->map.rend(); }
		inline IteratorReverse rend()						{ return this->map.rend(); }

		inline int size() const								{ return this->map.size(); }

		inline const std::map<Key*,Value>& getMap() const	{ return this->map; }
		inline std::map<Key*,Value>& getMap()				{ return this->map; }

		inline void transactionBeginRead() const			{ this->mux.lockForRead(); }
		inline void transactionBeginWrite() const			{ this->mux.lockForWrite(); }
		inline void transactionEnd() const					{ this->mux.unLock(); }

		inline MutexRW* getMutex() const					{ return &this->mux; }

//@}
		virtual MapT<Key*,Value>& operator=(const MapT<Key*,Value>& ) {
			return *this;
		 }

		virtual bool operator==( const MapT<Key*,Value>& other ) const {
			this->transactionBeginRead();
			other.transactionBeginRead();
			if ( this->map.size() != other.map.size() ) {
				other.transactionEnd();
				this->transactionEnd();
				return false;
			 }
			bool result = std::equal( this->map.begin(), this->map.end(), other.map.begin() );
			other.transactionEnd();
			this->transactionEnd();
			return result;
		 }

		virtual bool operator!=( const MapT<Key*,Value> &other ) const	{ return !(*this == other);  }


	protected:
		mutable std::map<Key*,Value> map;
		mutable MutexRW mux;

}; // class def

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////


/**
 * @class   wosh::TreeNodeT
 * @brief   
 ****************************************************************************
 *
 * @ingroup DataModels
 ****************************************************************************
 * @version 0.8.384 $Id $
 * @author  Alessandro Polo
 ****************************************************************************/
template <typename T>  
class TreeNodeT
 {
	public:

	typedef ListT<TreeNodeT<T>*> tTreeNodeTList;
	typedef typename tTreeNodeTList::Iterator ChildIterator;
	typedef typename tTreeNodeTList::ConstIterator ChildConstIterator;


	public:
		TreeNodeT( const T& data, TreeNodeT<T>* node_parent = NULL )
			: parent(node_parent), content(data) { 
			if ( this->parent != NULL ) {
				this->parent->children.push_back(this, false);
			 }
		}

		TreeNodeT( TreeNodeT<T>* node_parent )
			: parent(node_parent) {
			if ( this->parent != NULL ) {
				this->parent->children.push_back(this, false);
			 }
		}

		TreeNodeT( const TreeNodeT<T>& ) {
		 }

		virtual ~TreeNodeT() { }


		void free( bool nested, bool ) {
			if ( !nested ) return;
			ChildIterator it;
			const ChildConstIterator it_end = this->children.end();
			for( it=this->children.begin(); it!=it_end; ++it) {
				(*it)->free(true, true);
			 }
			this->children.free();
		 }


		inline ChildConstIterator begin() const			{ return this->children.begin(); }
		inline ChildIterator begin()					{ return this->children.begin(); }

		inline ChildConstIterator end() const			{ return this->children.end(); }
		inline ChildIterator end()						{ return this->children.end(); }


		const TreeNodeT<T>* getParent() const			{ return this->parent; }
		TreeNodeT<T>* getParent()						{ return this->parent; }

		const tTreeNodeTList& getChildren() const		{ return this->children; }
		tTreeNodeTList& getChildren()					{ return this->children; }


		TreeNodeT<T>* addChild( const T& data ) {
			TreeNodeT<T>* child = new TreeNodeT<T>(data, this);
			return child;
		 }

		void setParent( TreeNodeT<T>* node, bool fix_references = false ) {
			if ( this->parent == node || this == node ) return;
			if ( fix_references && this->parent != NULL ) {
				if ( this->parent != NULL ) {
					this->parent->children.pop(this);
				 }
			 }
			this->parent = node;
			if ( fix_references && node != NULL ) {
				node->children.push_back(this, false); // add if not present
			 }
		 }

		int mergeChildren( const TreeNodeT<T>* other ) {
			if ( other == NULL ) return 0;
			int count = 0;
			ChildConstIterator it, ito;
			const ChildConstIterator it_end = this->children.end();
			const ChildConstIterator ito_end = other->children.end();
			for( ito=other->children.begin(); ito!=ito_end; ++ito ) {
				TreeNodeT<T>* foundNode = NULL;
				if ( *ito == NULL ) continue;
				for( it=this->children.begin(); it!=it_end; ++it ) {
					if ( *it == NULL ) continue;
					if ( (*it)->content != (*ito)->content ) continue;
					foundNode = *it;
					break;
				 }
				if ( foundNode == NULL ) {
					foundNode = addChild( (*ito)->content );
					++count;
				 }
				count += foundNode->mergeChildren(*ito); // recursive
			 }
			return count;
		 }

		void setContent( const T& object ) {
			this->content = object;
		 }

		const T& getContent() const					{ return this->content; }
		T& getContent()								{ return this->content; }

		inline void transactionBeginRead() const			{ this->mux.lockForRead(); }
		inline void transactionBeginWrite() const			{ this->mux.lockForWrite(); }
		inline void transactionEnd() const					{ this->mux.unLock(); }

		inline MutexRW* getMutex() const				{ return &this->mux; }


	protected:
		TreeNodeT* parent;
		tTreeNodeTList children;
		T content;

		mutable MutexRW mux;

}; // class def

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////

template <typename T>  
class TreeNodeT<T*>
 {
	public:

	typedef ListT<TreeNodeT<T*>*> tTreeNodeTList;
	typedef typename tTreeNodeTList::Iterator ChildIterator;
	typedef typename tTreeNodeTList::ConstIterator ChildConstIterator;


	public:
		TreeNodeT( TreeNodeT<T*>* node_parent, T* data = NULL )
			: parent(node_parent), content(data) { 
			if ( this->parent != NULL ) {
				this->parent->getChildren().push_back(this, false);
			 }
		}

		TreeNodeT( const TreeNodeT<T*>& )
			: parent(NULL), content(NULL) { }

		virtual ~TreeNodeT() {
			
		 }

		void free( bool nested, bool delete_content ) {
			if ( delete_content )
				setContent( NULL, true );
			if ( !nested ) return;
			ChildIterator it;
			const ChildConstIterator it_end = this->children.end();
			for( it=this->children.begin(); it!=it_end; ++it) {
				(*it)->free(true, delete_content);
			 }
			this->children.free();
		 }


		inline ChildConstIterator begin() const		{ return this->children.begin(); }
		inline ChildIterator begin()				{ return this->children.begin(); }

		inline ChildConstIterator end() const		{ return this->children.end(); }
		inline ChildIterator end()					{ return this->children.end(); }


		const TreeNodeT<T*>* getParent() const		{ return this->parent; }
		TreeNodeT<T*>* getParent()					{ return this->parent; }

		const tTreeNodeTList& getChildren() const		{ return this->children; }
		tTreeNodeTList& getChildren()					{ return this->children; }


		TreeNodeT<T*>* addChild( T* data ) {
			TreeNodeT<T*>* child = new TreeNodeT<T*>(this, data);
			return child;
		 }

		void setParent( TreeNodeT<T*>* node, bool fix_references = false ) {
			if ( this->parent == node || this == node ) return;
			if ( fix_references && this->parent != NULL ) {
				if ( this->parent != NULL ) {
					this->parent->getChildren().pop(this);
				 }
			 }
			this->parent = node;
			if ( fix_references && node != NULL ) {
				node->getChildren().push_back(this, false); // add if not present
			 }
		 }

		int mergeChildren( const TreeNodeT<T*>* other, bool acquire_content = false ) {
			if ( other == NULL ) return 0;
			int count = 0;
			ChildConstIterator it, ito;
			const ChildConstIterator it_end = this->children.end();
			const ChildConstIterator ito_end = other->children.end();
			for( ito=other->children.begin(); ito!=ito_end; ++ito ) {
				TreeNodeT<T>* foundNode = NULL;
				if ( *ito == NULL ) continue;
				for( it=this->children.begin(); it!=it_end; ++it ) {
					if ( *it == NULL ) continue;
					if ( ((*ito)->content == NULL) ^ ((*it)->content == NULL) ) continue;
					foundNode = *it;
					break;
				 }
				if ( foundNode == NULL ) {
					if ( acquire_content || (*ito)->content == NULL ) {
						foundNode = addChild( (*ito)->content );
						(*ito)->content = NULL; // acquire, pop the content
					 }
					else
						foundNode = addChild( new T(*(*ito)->content) );
					++count;
				 }
				count += foundNode->mergeChildren(*ito); // recursive
			 }
			return count;
		 }

		void setContent( T* object, bool delete_previous = true ) {
			if ( delete_previous == true && this->content != NULL && this->content != object )
				delete this->content;
			this->content = object;
		 }

		const T* getContent() const							{ return this->content; }
		T* getContent()										{ return this->content; }

		bool hasContent() const								{ return (this->content != NULL); }

		inline void transactionBeginRead() const			{ this->mux.lockForRead(); }
		inline void transactionBeginWrite() const			{ this->mux.lockForWrite(); }
		inline void transactionEnd() const					{ this->mux.unLock(); }

		inline MutexRW* getMutex() const					{ return &this->mux; }


	protected:
		TreeNodeT* parent;
		T* content;
		tTreeNodeTList children;

		mutable MutexRW mux;

}; // class def

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/**
 * @class   wosh::TreeT
 * @brief   
 ****************************************************************************
 *
 * @ingroup DataModels
 ****************************************************************************
 * @version 0.8.384 $Id $
 * @author  Alessandro Polo
 ****************************************************************************/
template <typename TREENODE_TYPE>
class TreeT
 {

	public:
		TreeT()
			: tree_name("Tree"), rootNode(NULL) { }
		TreeT( const TreeT<TREENODE_TYPE>& m )
			: tree_name(m.tree_name), rootNode(NULL) {
			
		 }
		virtual ~TreeT() { }


		void free( bool nested, bool delete_content ) {
			if ( this->rootNode == NULL )
				return;
			this->rootNode->free(nested, delete_content);
			delete this->rootNode; this->rootNode = NULL;
		 }

	public:
		inline const TREENODE_TYPE* getRoot() const		{ return this->rootNode; }
		inline TREENODE_TYPE* getRoot()					{ return this->rootNode; }

		inline bool hasRoot() const							{ return (this->rootNode != NULL); }

		void setRoot( TREENODE_TYPE* root_node, bool deletePrevious = true ) {
			if ( deletePrevious && this->rootNode != NULL ) delete this->rootNode; this->rootNode = NULL;
			this->rootNode = root_node;
		 }

		inline bool isEmpty() const {
			if ( this->rootNode == NULL )
				return true;
			return this->rootNode->isEmpty();
		 }

		inline const std::string& getTreeName() const		{ return this->tree_name; }
		inline std::string& getTreeName()					{ return this->tree_name; }

		void setTreeName( const std::string& name ) 		{ this->tree_name = name; }

	protected:
		std::string tree_name;							///< name of the tree
		mutable TREENODE_TYPE* rootNode;

}; // class def



}; // namespace wosh

#endif //__WOSH_Core_Containers_H__
